﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Linq;

namespace YABE.Models
{
    
    public interface ICommentDL
    {
        List<Comment> GetCommentsByPostID(int PostID);
        List<Comment> GetCommentsByPost(Post post);
        void AddCommentToPost(Post post, Comment comment);
        void ApproveComment(Comment comment);
        void UnApproveComment(Comment comment);
        void DeleteComment(Comment comment);
        List<Comment> GetCommentsByUserIP(string UserIP);
        List<Comment> GetCommentsByUserEmail(string UserEmail);
        Comment GetLatestCommentByCommentor(string UserIP);
    }
    
    public class CommentDL:ICommentDL
    {
        
        /// <summary>
        /// Lists  comments to a post that is specified by postid
        /// </summary>
        /// <param name="PostID">PostID for the post</param>
        /// <returns>List of comments</returns>
        public List<Comment> GetCommentsByPostID(int PostID)
        {
            using (YabeDataContext context = YabeDataManager.Instance.DataContext)
            {
                List<Comment> comments = (from c in context.Comments
                                          where c.PostID == PostID
                                          select c).ToList();

                return comments;
            }
        }


        /// <summary>
        /// Returns list of comments for a specified post
        /// </summary>
        /// <param name="post"></param>
        /// <returns></returns>
        public List<Comment> GetCommentsByPost(Post post)
        {
            using (YabeDataContext context = YabeDataManager.Instance.DataContext)
            {
                List<Comment> comments = (from c in context.Comments
                                          where c.Post == post
                                          select c).ToList();
                return comments;
            }
        }

        /// <summary>
        /// Adds a comment to a post
        /// </summary>
        /// <param name="post">Post that comment will be added to</param>
        /// <param name="comment">Comment that will be added</param>
        public void AddCommentToPost(Post post, Comment comment)
        {
            using (YabeDataContext context = YabeDataManager.Instance.DataContext)
            {
                //look if the post exists
                var postinDB = (from p in context.Posts
                                 where p == post
                                 select p).SingleOrDefault();
                if (null == postinDB)
                {
                    throw new Exception("This post does not exist");
                }

              //attach post to context
                context.Posts.Attach(post);
                try
                {
                    post.Comments.Add(comment);
                    context.SubmitChanges(ConflictMode.ContinueOnConflict);

                }
                catch (ChangeConflictException)
                {
                    context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);
                        //User values will be keeped on the resolution
                }
            }
        }


        /// <summary>
        /// Approves a comment, approving means simply changing approve field to true
        /// </summary>
        /// <param name="comment">Comment to act on</param>
        public void ApproveComment(Comment comment)
        {
            CommentApproval(comment,true);
        }

        /// <summary>
        /// Approves or Unapproves a comment 
        /// </summary>
        /// <param name="comment">Comment to act on</param>
        /// <param name="Approval">if true, approves, else false unapproves</param>
        private void CommentApproval(Comment comment,bool Approval)
        {
            using (YabeDataContext context = YabeDataManager.Instance.DataContext)
            {
                //look if the comment exists
                var commentinDB = (from c in context.Comments
                                   where c == comment
                                   select c).SingleOrDefault();
                if(null==commentinDB)
                {
                    throw new Exception("This comment does not exist");
                }
                //attach comment to context
                context.Comments.Attach(comment);
                try
                {
                    comment.IsApproved = Approval;
                    context.SubmitChanges(ConflictMode.ContinueOnConflict);
                }
                catch (ChangeConflictException)
                {
                    context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);
                    //User values will be keeped on the resolution
                }
            }
        }

        /// <summary>
        /// Unapproves a comment, unapproving means simply changing approve field to false
        /// </summary>
        /// <param name="comment">Comment to act on</param>
        public void UnApproveComment(Comment comment)
        {
            CommentApproval(comment, false);
        }

        public void DeleteComment(Comment comment)
        {
            using (YabeDataContext context = YabeDataManager.Instance.DataContext)
            {
                //look if the comment exists
                var commentinDB = (from c in context.Comments
                                   where c == comment
                                   select c).SingleOrDefault();
                if (null == commentinDB)
                {
                    throw new Exception("This comment does not exist");
                }
                //attach comment to context
                context.Comments.Attach(comment);
                try
                {
                   context.Comments.DeleteOnSubmit(comment);
                   context.SubmitChanges(ConflictMode.ContinueOnConflict);
                }
                catch (ChangeConflictException)
                {
                    context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);
                    //User values will be keeped on the resolution
                }
            }
        }
        public List<Comment> GetCommentsByUserIP(string UserIP)
        {
            using (YabeDataContext context = YabeDataManager.Instance.DataContext)
            {
                var comments = (from c in context.Comments
                                where c.ClientIP == UserIP
                                select c).ToList();
                return comments;
            }
        }

        public List<Comment> GetCommentsByUserEmail(string UserEmail)
        {
            using (YabeDataContext context = YabeDataManager.Instance.DataContext)
            {
                var comments = (from c in context.Comments
                                where c.Email.ToLowerInvariant().Trim() == UserEmail.ToLowerInvariant().Trim()
                                select c).ToList();
                return comments;
            }
        }

        public Comment GetLatestCommentByCommentor(string UserIP)
        {
            using (YabeDataContext context = YabeDataManager.Instance.DataContext)
            {
                var comment = (from c in context.Comments
                               where c.ClientIP == UserIP
                               orderby c.Created descending 
                               select c).FirstOrDefault();
                return comment;
            }
        }
    }
}
